#include "audiofile.h"
#include "playlistentry.h"

#include "id3tag.h"

#include "debugmodule.h"

QIcon AudioFile::DEFAULT_ICON = QIcon();

AudioFile::AudioFile(const QString& i_filepath) :
    m_fileInfo(i_filepath), m_filename(m_fileInfo.completeBaseName()),
    m_tagsRead(false), m_hasLyrics(false),
    m_hasCover(false),
    m_cover(DEFAULT_ICON)
{
    if (DEFAULT_ICON.isNull())
    {
        DEFAULT_ICON = QIcon(":/icons/audioFile");
        m_cover = DEFAULT_ICON;
    }
}

AudioFile::~AudioFile()
{
    foreach (PlaylistEntry* pEntry, m_playlistEntries)
        pEntry->removeAudioFile();
}

void AudioFile::addPlaylistEntry(PlaylistEntry* i_pEntry)
{
    m_playlistEntries << i_pEntry;
    emit dataChanged();
}

void AudioFile::removePlaylistEntry(PlaylistEntry* i_pEntry)
{
    m_playlistEntries.remove(i_pEntry);
    emit dataChanged();
}

void AudioFile::readTags(bool i_refresh)
{
    if (m_tagsRead && !i_refresh)
        return;

    id3_file* pFile = id3_file_open(qPrintable(m_fileInfo.absoluteFilePath()), ID3_FILE_MODE_READONLY);
    if (pFile == NULL)
        return;

    // Verfügbare Tags
    QStringList tagStrings;
    for (uint i = 0; i < pFile->ntags; i++)
    {
        QString v2String;
        if ((pFile->tags[i].tag->options & ID3_TAG_OPTION_ID3V1) == 0)
            v2String = "2.";

        const uint version = pFile->tags[i].tag->version;
        tagStrings << QString("ID3v%1%2.%3").
                      arg(v2String).
                      arg(ID3_TAG_VERSION_MAJOR(version)).
                      arg(ID3_TAG_VERSION_MINOR(version));
    }
    m_tagString = tagStrings.join(';');

    id3_tag* pTag = id3_file_tag(pFile);

    // Verfügbare Frames
    /*uint fid = 0;
    id3_frame* pTestFrame;
    while (pTestFrame = id3_tag_findframe(pTag, 0, fid++))
    {
        qDebug("%s", pTestFrame->id);
    }*/

    // Interpret
    m_artist = getTagTextField(pTag, "TPE1");
    // Titel
    m_title = getTagTextField(pTag, "TIT2");
    // Album
    m_album = getTagTextField(pTag, "TALB");
    // Genre
    m_genre = getTagTextField(pTag, "TCON");
    // Track
    m_track = getTagTextField(pTag, "TRCK");
    // Year
    m_year = getTagTextField(pTag, "TDRC");

    // Lyrics
    m_hasLyrics = hasTagUnsyncedLyrics(pTag) || hasTagSyncedLyrics(pTag);

    // Cover
    m_hasCover = false;
    id3_frame* pFrame;
    uint i = 0;
    while((pFrame = id3_tag_findframe(pTag, "APIC", i++)))
    {
        // Bildtyp
        // FieldType 10 == INT8, value 3 == Cover front
        id3_field* pField = id3_frame_field(pFrame, 2);
        if (pField && pField->type == 10 && pField->number.value == 3)
        {
            // Binärdaten
            pField = id3_frame_field(pFrame, 4);
            if (pField && pField->type == ID3_FIELD_TYPE_BINARYDATA)
            {
                QPixmap cover;
                m_hasCover = cover.loadFromData(pField->binary.data, pField->binary.length);

                if (m_hasCover)
                {
                    // Cover gefunden
                    m_cover = cover;
                    break;
                }
            }
        }
    }

    if (!m_hasCover)
    {
        m_cover = DEFAULT_ICON;
    }

    id3_file_close(pFile);

    m_tagsRead = true;
    //emit dataChanged();
}

QString AudioFile::getTagTextField(id3_tag* i_pTag, const char* i_frame)
{
    id3_frame* pFrame = id3_tag_findframe(i_pTag, i_frame, 0);
    if (pFrame)
    {
        id3_field* pField = id3_frame_field(pFrame, 1);
        if (pField && pField->type == ID3_FIELD_TYPE_STRINGLIST && pField->stringlist.nstrings > 0)
        {
            QVector<QChar> temp;
            id3_ucs4_t* pString = pField->stringlist.strings[0];

            while(*pString)
            {
                temp << (ushort)*pString;
                ++pString;
            }

            temp << 0;
            return QString(temp.constData());
        }
    }

    return QString();
}

bool AudioFile::hasTagUnsyncedLyrics(id3_tag* i_pTag)
{
    id3_frame* pFrame;
    uint i = 0;
    while ((pFrame = id3_tag_findframe(i_pTag, "USLT", i++)))
    {
        id3_field* pField = id3_frame_field(pFrame, 3);

        if (pField && pField->string.ptr && pField->string.ptr[0])
            return true;
    }

    return false;
}

bool AudioFile::hasTagSyncedLyrics(id3_tag* i_pTag)
{
    id3_frame* pFrame;
    uint i = 0;
    while ((pFrame = id3_tag_findframe(i_pTag, "SYLT", i++)))
    {
        id3_field* pField = id3_frame_field(pFrame, 5);

        if (pField && pField->binary.length > 0)
            return true;
    }

    return false;
}
